<script setup lang="ts">
import OpenAiApi from '@/api/openAi'
import OpenAI from 'openai'
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/store/modules/user'

const openai = ref<OpenAI>()
const messageList = ref<
  Array<{
    id: string
    role: 'user' | 'assistant'
    content: string
    isTyping?: boolean
  }>
>([])
const inputMessage = ref('')
const isLoading = ref(false)

const userInfo = computed(() => {
  return useUserStore().userInfo
})

onMounted(() => {
  initData()
})

async function initData() {
  const res = await OpenAiApi.getKey()
  if (res.success) {
    openai.value = new OpenAI({
      baseURL: 'https://api.deepseek.com',
      apiKey: res.message,
      dangerouslyAllowBrowser: true,
    })
  }
}

const formatMessage = (content: string) => {
  let isInCodeBlock = false
  let formattedContent = ''
  let codeBlockId = 0

  const lines = content.split('\n')
  for (let i = 0; i < lines.length; i++) {
    const line = lines[i]

    if (line.startsWith('```')) {
      isInCodeBlock = !isInCodeBlock
      if (isInCodeBlock) {
        codeBlockId++
        formattedContent += `<div class="code-block-wrapper">
          <div class="code-header">
            <span class="language">${line.slice(3) || 'code'}</span>
            <button class="copy-btn" onclick="copyCode(${codeBlockId})">
              <el-icon><Document /></el-icon>
              复制代码
            </button>
          </div>
          <pre class="code-block" id="code-${codeBlockId}">`
      } else {
        formattedContent += '</pre></div>'
      }
      continue
    }

    if (isInCodeBlock) {
      formattedContent += line + '\n'
    } else {
      formattedContent += line + '<br>'
    }
  }

  return formattedContent
}

// 添加到 window 对象以便在 onclick 中调用
window.copyCode = (id: number) => {
  const codeBlock = document.getElementById(`code-${id}`)
  if (codeBlock) {
    const text = codeBlock.textContent || ''
    navigator.clipboard
      .writeText(text)
      .then(() => {
        ElMessage.success('代码已复制到剪贴板')
      })
      .catch(() => {
        ElMessage.error('复制失败')
      })
  }
}

async function handleSendMessage() {
  if (!inputMessage.value.trim() || !openai.value) return

  const messageId = Date.now().toString()
  const userMessage = inputMessage.value

  inputMessage.value = ''
  isLoading.value = true

  messageList.value.push({
    id: `user-${messageId}`,
    role: 'user',
    content: userMessage,
  })

  const aiMessage = {
    id: `ai-${messageId}`,
    role: 'assistant',
    content: '',
    isTyping: true,
  }
  messageList.value.push(aiMessage)

  try {
    const completion = await openai.value.chat.completions.create({
      messages: [
        { role: 'system', content: 'You are a helpful assistant.' },
        ...messageList.value
          .filter((msg) => !msg.isTyping)
          .map(({ role, content }) => ({ role, content })),
      ],
      model: 'deepseek-chat',
    })

    const aiResponse =
      completion?.choices[0]?.message?.content || '抱歉，我没有得到有效的回复'

    // 重新实现打字机效果
    const typeWriter = async (text: string) => {
      const aiMessageIndex = messageList.value.findIndex(
        (msg) => msg.id === `ai-${messageId}`
      )
      if (aiMessageIndex === -1) return

      let currentText = ''
      for (let i = 0; i < text.length; i++) {
        currentText += text[i]
        messageList.value[aiMessageIndex].content = formatMessage(currentText)
        // 使用 await 来创建真实的延迟
        await new Promise((resolve) => setTimeout(resolve, 20))
      }
      messageList.value[aiMessageIndex].isTyping = false
    }

    await typeWriter(aiResponse)
  } catch (error) {
    console.error('Error:', error)
    const errorMessage = '抱歉，发生了一些错误，请稍后重试。'
    const aiMessageIndex = messageList.value.findIndex(
      (msg) => msg.id === `ai-${messageId}`
    )
    if (aiMessageIndex !== -1) {
      messageList.value[aiMessageIndex].content = errorMessage
      messageList.value[aiMessageIndex].isTyping = false
    }
  } finally {
    isLoading.value = false
  }
}
</script>

<template>
  <div class="chat-container">
    <div class="chat-header">
      <h2>AI 助手</h2>
    </div>

    <!-- 消息列表 -->
    <div class="message-list">
      <template v-if="messageList.length === 0">
        <div class="empty-state">
          <div class="empty-icon">🤖</div>
          <p>有什么可以帮忙的吗？</p>
        </div>
      </template>

      <div
        v-for="message in messageList"
        v-else
        :key="message.id"
        :class="['message', message.role]">
        <div class="message-content">
          <div class="avatar">
            <el-avatar
              v-if="message.role === 'user'"
              :size="40"
              :src="userInfo?.avatar" />
            <el-icon v-else><Service /></el-icon>
          </div>
          <div class="content">
            <div class="text" v-html="message.content"></div>
            <div v-if="message.isTyping" class="typing-indicator">
              <span></span>
              <span></span>
              <span></span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 输入区域 -->
    <div class="input-area">
      <div class="input-wrapper">
        <el-input
          v-model="inputMessage"
          type="textarea"
          :rows="3"
          resize="none"
          placeholder="输入消息..."
          @keydown.enter.prevent="handleSendMessage" />
        <el-button
          type="primary"
          :disabled="isLoading || !inputMessage.trim()"
          @click="handleSendMessage">
          <el-icon><Position /></el-icon>
          发送
        </el-button>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.chat-container {
  margin-top: 20px;
  height: calc(100vh - 60px); // 减去顶部导航的高度
  display: flex;
  flex-direction: column;
  background-color: #ffffff;
  border-radius: 8px;
  overflow: hidden;
}

.chat-header {
  padding: 16px 24px;
  border-bottom: 1px solid #e6e6e6;

  h2 {
    color: #333333;
    margin: 0;
    font-size: 18px;
  }
}

.message-list {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 24px;

  &::-webkit-scrollbar {
    width: 6px;
  }

  &::-webkit-scrollbar-thumb {
    background-color: #e0e0e0;
    border-radius: 3px;
  }
}

.empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #666666;

  .empty-icon {
    font-size: 48px;
    margin-bottom: 16px;
  }

  p {
    font-size: 16px;
    margin: 0;
  }
}

.message {
  max-width: 80%;

  &.user {
    margin-left: auto;

    .message-content {
      flex-direction: row-reverse;
    }

    .content {
      background-color: #e8f3ff;
      margin-left: 0;
      margin-right: 12px;
      color: #333333;
    }
  }
}

.message-content {
  display: flex;
  align-items: flex-start;
}

.avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;

  :deep(.el-icon) {
    font-size: 20px;
    color: #666666;
  }
}

.content {
  background-color: #f5f5f5;
  padding: 12px 16px;
  border-radius: 12px;
  margin-left: 12px;
  color: #333333;
  font-size: 14px;
  line-height: 1.6;

  :deep(.code-block) {
    background-color: #f8f8f8;
    border: 1px solid #e0e0e0;
    border-radius: 4px;
    padding: 8px 12px;
    margin: 8px 0;
    font-family: monospace;
    white-space: pre-wrap;
    word-break: break-all;
  }
}

.typing-indicator {
  display: inline-flex;
  gap: 4px;
  padding: 4px 8px;

  span {
    width: 4px;
    height: 4px;
    background-color: #666;
    border-radius: 50%;
    animation: typing 1s infinite ease-in-out;

    &:nth-child(1) {
      animation-delay: 0.2s;
    }
    &:nth-child(2) {
      animation-delay: 0.3s;
    }
    &:nth-child(3) {
      animation-delay: 0.4s;
    }
  }
}

.input-area {
  padding: 16px 24px;
  border-top: 1px solid #e6e6e6;

  .input-wrapper {
    display: flex;
    gap: 12px;

    :deep(.el-textarea__inner) {
      background-color: #ffffff;
      border-color: #dcdfe6;
      color: #333333;

      &:focus {
        border-color: #409eff;
      }
    }

    .el-button {
      .el-icon {
        margin-right: 4px;
      }
    }
  }
}

@keyframes typing {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-4px);
  }
}

.code-block-wrapper {
  margin: 16px 0;
  border-radius: 8px;
  overflow: hidden;
  background-color: #282c34;

  .code-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 16px;
    background-color: #21252b;
    border-bottom: 1px solid #181a1f;

    .language {
      color: #abb2bf;
      font-size: 12px;
      text-transform: lowercase;
    }

    .copy-btn {
      display: flex;
      align-items: center;
      gap: 4px;
      padding: 4px 8px;
      border: none;
      border-radius: 4px;
      background-color: #353b45;
      color: #abb2bf;
      cursor: pointer;
      font-size: 12px;
      transition: all 0.2s;

      &:hover {
        background-color: #3e4451;
      }

      .el-icon {
        font-size: 14px;
      }
    }
  }

  .code-block {
    margin: 0;
    padding: 16px;
    background-color: #282c34;
    color: #abb2bf;
    font-family: 'Fira Code', monospace;
    font-size: 14px;
    line-height: 1.5;
    overflow-x: auto;

    &::-webkit-scrollbar {
      height: 8px;
    }

    &::-webkit-scrollbar-thumb {
      background-color: #4b5263;
      border-radius: 4px;
    }

    &::-webkit-scrollbar-track {
      background-color: #21252b;
    }
  }
}

// 确保普通文本的样式不受代码块影响
.content {
  .text {
    > p,
    > br {
      color: #333333;
    }
  }
}
</style>
